//
//  UIViewController+BQTop.m
//  BQNavigator
//
//  Created by Zhiqiang Bao on 15-4-1.
//  Copyright (c) 2015年 Zhiqiang Bao. All rights reserved.
//

#import "UIViewController+BQTop.h"
#import <objc/runtime.h>

@interface BQTopViewControllerManager : NSObject

@property (nonatomic, strong) NSMutableArray *viewCtrStack;
@property (nonatomic, strong) NSMutableArray *navCtrStack;

@end

@implementation BQTopViewControllerManager

+ (BQTopViewControllerManager *)sharedInstance
{
    static dispatch_once_t onceTocken;
    static BQTopViewControllerManager *sharedInstance = nil;
    
    dispatch_once(&onceTocken, ^{
        if (sharedInstance == nil) {
            sharedInstance = [[self alloc] init];
        }
    });
    
    return sharedInstance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.viewCtrStack = [NSMutableArray array];
        self.navCtrStack = [NSMutableArray array];
    }
    return self;
}

- (void)pushNavigationController:(UIViewController *)nav
{
    if (nav) {
        [_navCtrStack addObject:nav];
    }
}

- (void)pushViewController:(UIViewController *)ctr
{
    if (ctr) {
        [_viewCtrStack addObject:ctr];
    }
}

- (UINavigationController *)popNavigationController
{
    UINavigationController *nav = _navCtrStack.lastObject;
    [_navCtrStack removeLastObject];
    return nav;
}

- (UIViewController *)popViewController
{
    UIViewController *ctr = _viewCtrStack.lastObject;
    [_viewCtrStack removeLastObject];
    return ctr;
}

- (UINavigationController *)topNavigationController
{
    return _navCtrStack.lastObject;
}

- (UIViewController *)topViewController
{
    return _viewCtrStack.lastObject;
}

@end

@implementation UIViewController (BQTop)

+ (void)load
{
    // exchange UIViewController viewWillAppear
    Method originalViewWillAppear = class_getInstanceMethod([UIViewController class], @selector(viewWillAppear:));
    Method targetViewWillAppear = class_getInstanceMethod([UIViewController class], @selector(topViewWillAppear:));
    method_exchangeImplementations(originalViewWillAppear, targetViewWillAppear);
    
    // exchange UIViewController viewWillDisappear
    Method originalViewWillDisappear = class_getInstanceMethod([UIViewController class], @selector(viewWillDisappear:));
    Method targetViewWillDisappear = class_getInstanceMethod([UIViewController class], @selector(topViewWillDisappear:));
    method_exchangeImplementations(originalViewWillDisappear, targetViewWillDisappear);
    
    // exchange UINavigationController viewWillAppear
    Method navOriginalViewWillAppear = class_getInstanceMethod([UINavigationController class], @selector(viewWillAppear:));
    Method navTargetViewWillAppear = class_getInstanceMethod([UINavigationController class], @selector(topNavViewWillAppear:));
    method_exchangeImplementations(navOriginalViewWillAppear, navTargetViewWillAppear);
    
    // exchange UINavigationController viewWillDisappear
    Method navOriginalViewWillDisappear = class_getInstanceMethod([UINavigationController class], @selector(viewWillDisappear:));
    Method navTargetViewWillDisappear = class_getInstanceMethod([UINavigationController class], @selector(topNavViewWillDisappear:));
    method_exchangeImplementations(navOriginalViewWillDisappear, navTargetViewWillDisappear);
}

- (void)topViewWillAppear:(BOOL)animated
{
    [[BQTopViewControllerManager sharedInstance] pushViewController:self];
    
    [self topViewWillAppear:animated];
}

- (void)topViewWillDisappear:(BOOL)animated
{
    [[BQTopViewControllerManager sharedInstance] popViewController];
    
    [self topViewWillDisappear:animated];
}

- (void)topNavViewWillAppear:(BOOL)animated
{
    [[BQTopViewControllerManager sharedInstance] pushNavigationController:self];
    
    [self topViewWillAppear:animated];
}

- (void)topNavViewWillDisappear:(BOOL)animated
{
    [[BQTopViewControllerManager sharedInstance] popNavigationController];
    
    [self topViewWillDisappear:animated];
}

#pragma mark - api

+ (UIViewController *)topViewController
{
    return [[BQTopViewControllerManager sharedInstance] topViewController];
}

+ (UINavigationController *)topNavigationController
{
    return [[BQTopViewControllerManager sharedInstance] topNavigationController];
}

@end
